package com.air.ota.util;

import java.io.*;
import java.util.*;

import com.air.ota.util.HexStringUtil;

public class PBOCUtil {
	private int h;
	static Enumeration portList;
	OutputStream outputStream;
	InputStream inputStream; //
	byte[] P_data = new byte[4094];
	byte[] PP_data = new byte[4094];
	byte[] Pboc_State_Ok = new byte[] { (byte) 0x90, 0x00 };
	byte[] Pboc_State_WriteOk = new byte[] { 0x66, 0x02 };
	byte[] LackBal_State = new byte[] { (byte) 0x94, 0x01 };
	byte[] Txdata = new byte[16];
	byte[] State_Ok = new byte[] { 0x00, 0x00 };
	byte[] State_Powerfail = new byte[] { (byte) 0xA0, 0x09 };
	byte[] State_Waitcard = new byte[] { (byte) 0xA0, 0x0A };
	byte[] State_Wrong = new byte[] { (byte) 0xE0, 0x55 };
	byte[] State_Cardlock = new byte[] { (byte) 0xE0, (byte) 0xAA };
	byte[] State_Unactive = new byte[] { (byte) 0xE0, 0x05 };
	byte[] State_UnFindcard = new byte[] { (byte) 0xA0, 0x01 };
	byte[] State_UnFindcard2 = new byte[] { (byte) 0xA0, 0x02 };
	byte[] State_UnFindcard3 = new byte[] { (byte) 0xA0, 0x06 };
	byte[] State_Receive = new byte[2];
	byte[] State_Pboc = new byte[2];
	 byte[]SdNumber=new byte[16];
	byte[] Shut = new byte[] { 0x02, 0x00, 0x04, (byte) 0xA2, 0x32, 0x00, 0x00,
			(byte) 0x90, 0x03 };
	int Data_len;
	int numBytes = 0;
	String str;
	String Realstr; // @jve:decl-index=0:

	byte[] Open = new byte[] { 0x02, 0x00, 0x04, (byte) 0xA2, 0x31, 0x00, 0x64,
			(byte) 0xF7, 0x03 };
	 byte[] Keynm = new byte[16];// {0x4B,0x33,(byte) 0x88,0x1E,(byte)
								// 0x8E,(byte) 0xB2,(byte) 0xF7,(byte) 0xB8,
	// (byte) 0x8F,0x26,0x10,0x09,(byte) 0xAA,(byte) 0x88,(byte) 0xA4,(byte)
	// 0xA3};
	static byte[] LoadKey = new byte[16];// {(byte) 0xC7,(byte) 0xC1,0x46,0x50,(byte)
									// 0xB1,0x3D,0x3D,
	// (byte) 0x9A,(byte) 0x8E,(byte) 0xE3,0x40,(byte) 0xA7,0x17,(byte)
	// 0x94,(byte) 0x8D,(byte) 0xE8};
	int Shutflag;
	int Openflag;
	final int BALANACE = 1;// ���
	final int CASH = 2;// ���
	final int RECORD = 3;// ��¼

	int Action;
	int RdCod;
	byte data[] = new byte[300];
	byte Tempdata[] = new byte[300];
	byte[] Rcdata = new byte[300];
	int TdLen;
	int Datalen;
	byte[] ChangeMoney = new byte[4];
	String Money;
	byte[] SESPK = new byte[8];// �����Կ
	int S_O_flag = 0;
	int Cmd_flag = 1;
	int Fcard = 0;
	int Fnum = 0;
	Thread FindCard;
	int Three_State;
	int Find_Card_Ok;
	int State;
	int Cash_State;
	int Read_State;
	int Load_State;
	int Cash_flag;
	int Stop = 0;
	int Extnal_State = 0;
	int Write_State = 0;
	int ReadMC_State = 0;
	int P_State = 0;
	int Tpstate;
	int Rdb_State = 0;
	int Rds_State = 0;
	int P_flag;
	int Cash_Type;
	/********** des **************/
	byte[] Invt = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
	byte[] Out;
	private static final long serialVersionUID = 1L;

	// private static final Object VK_ENTER = null;
	/**************** 16���ƴ�ת�����ֽ����� ********************/

	public static byte[] hexStringToBytes(String hexString) {
		if ((hexString == null) || (hexString.equals(""))) {
			return null;
		}
		hexString = hexString.toUpperCase();

		int length = hexString.length() / 2;
		char[] a = new char[200];
		a[0] = '0';
		char[] hexChars = hexString.toCharArray();
		if (hexString.length() % 2 != 0) {
			length = length + 1;
			System.arraycopy(hexChars, 0, a, 1, hexString.length());
			// System.arraycopy(a, 0, hexChars,0,2*length);
		} else
			System.arraycopy(hexChars, 0, a, 0, hexString.length());
		byte[] d = new byte[length];
		for (int i = 0; i < length; ++i) {
			int pos = i * 2;
			// d[i] = (byte)(charToByte(hexChars[pos]) << 4 |
			// charToByte(hexChars[(pos + 1)]));
			d[i] = (byte) (charToByte(a[pos]) << 4 | charToByte(a[(pos + 1)]));
		}
		return d;
	}

	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	// �ֽ�����ת����16���ƴ�
	public static String byte2HexStr(byte[] b, int length) {
		String hs = "";
		String stmp = "";
		for (int n = 0; n < length; ++n) {
			stmp = Integer.toHexString(b[n] & 0xFF);
			if (stmp.length() == 1)
				hs = hs + "0" + stmp;
			else {
				hs = hs + stmp;
			}
		}
		return hs.toUpperCase();
	}

	// private String key;
	// ���������ֽ�����
	/**
	 * DES�㷨��64λ�������������64λ����������飬����ʹ�õ���ԿҲ��64λ, �书���ǰ������64λ��ݿ鰴λ������ϣ�
	 * ��������֞�L0��R0�����֣�ÿ���ָ���32λ�����û�������±� ��������ĵ�58λ������һλ����50λ������2λ��...���������ƣ�
	 * ���һλ��ԭ���ĵ�7λ��L0��R0���ǻ�λ�����������֣� L0���������32λ��R0 ����32λ��
	 * �����û�ǰ������ֵ��D1D2D3......D64�� �򾭹��ʼ�û���Ľ��飺L0=D550...D8��R0=D57D49...D7
	 */
	private static final int[] IP = { // OK
	58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46,
			38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33,
			25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29,
			21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 }; // 64
	/**
	 * ����26�ε������󡣵õ�L16��R16�������������룬�������û������õ����������
	 * ���û�����ǳ�ʼ�õ������㣬���磬��1λ�����ʼ�û��󣬴�춵�40λ�� ��ͨ�����û����ֽ���40λ���ص���1λ�������û��������±���ʾ��
	 */
	private static final int[] IP_1 = { // OK
	40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46,
			14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12,
			52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50,
			18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 }; // 64
	/**
	 * PC1�û�
	 */
	private static final int[] PC_1 = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50,
			42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44,
			36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6,
			61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 }; // 56
	/**
	 * PC2�û�
	 */
	private static final int[] PC_2 = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21,
			10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47,
			55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36,
			29, 32 }; // 48
	/**
	 * �Ŵ�λ��
	 */
	private static final int[] E = { // OK
	32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15,
			16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26,
			27, 28, 29, 28, 29, 30, 31, 32, 1 }; // 48
	/**
	 * ������λ��
	 */
	private static final int[] P = { // OK
	16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14,
			32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 }; // 32
	/**
	 * ��f(Ri,Ki)�㷨����ͼ�У�S1,S2...S8��ѡ�����书���ǰ�6bit��ݱ��4bit��ݡ�
	 * ������ѡ����Si(i=1,2......8)�Ĺ��ܱ?ѡ����Si
	 */
	private static final int[][][] S_Box = {
			{// S_Box[1] OK
			{ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },
					{ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },
					{ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },
					{ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } },
			{ // S_Box[2] OK
			{ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
					{ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },
					{ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },
					{ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } },
			{ // S_Box[3] OK
			{ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
					{ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },
					{ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },
					{ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } },
			{ // S_Box[4] OK
			{ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
					{ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },
					{ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },
					{ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } },
			{ // S_Box[5] OK
			{ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
					{ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 },
					{ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },
					{ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } },
			{ // S_Box[6] OK
			{ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
					{ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },
					{ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },
					{ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } },
			{ // S_Box[7] OK
			{ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
					{ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },
					{ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },
					{ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } },
			{ // S_Box[8] OK
			{ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
					{ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },
					{ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },
					{ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } } };
	/**
	 * ѭ������λ�� 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
	 */
	private static final int[] LeftMove = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
			2, 2, 2, 1 }; // ����λ���б�

	private byte[] UnitDes(byte[] des_key, byte[] des_data, int flag) {
		// �����������ʽ�Ƿ���ȷ������ֱ�ӷ��ؿ�ֵ��null��
		if ((des_key.length != 8) || (des_data.length != 8)
				|| ((flag != 1) && (flag != 0))) {
			throw new RuntimeException("Data Format Error !");
		}
		int flags = flag;
		// �����Ƽ�����Կ
		int[] keydata = new int[64];
		// �����Ƽ������
		int[] encryptdata = new int[64];
		// ���ܲ�����ɺ���ֽ�����
		byte[] EncryptCode = new byte[8];
		// ��Կ���Ի��ɶ�ά����
		int[][] KeyArray = new int[16][48];
		// ����Կ�ֽ�����ת���ɶ������ֽ�����
		keydata = ReadDataToBirnaryIntArray(des_key);
		// ����������ֽ�����ת���ɶ������ֽ�����
		encryptdata = ReadDataToBirnaryIntArray(des_data);
		// ���Ի���ԿΪ��ά��Կ����
		KeyInitialize(keydata, KeyArray);
		// ִ�м��ܽ��ܲ���
		EncryptCode = Encrypt(encryptdata, flags, KeyArray);
		return EncryptCode;
	}

	// ���Ի���Կ����
	private void KeyInitialize(int[] key, int[][] keyarray) {
		int i;
		int j;
		int[] K0 = new int[56];
		// �ر�ע�⣺xxx[IP[i]-1]�����Ʊ任
		for (i = 0; i < 56; i++) {
			K0[i] = key[PC_1[i] - 1]; // ��Կ����PC-1�任
		}
		for (i = 0; i < 16; i++) {
			LeftBitMove(K0, LeftMove[i]);
			// �ر�ע�⣺xxx[IP[i]-1]�����Ʊ任
			for (j = 0; j < 48; j++) {
				keyarray[i][j] = K0[PC_2[j] - 1]; // �������Կkeyarray[i][j]
			}
		}
	}
	// ִ�м��ܽ��ܲ���
	private byte[] Encrypt(int[] timeData, int flag, int[][] keyarray) {
		int i;
		byte[] encrypt = new byte[8];
		int flags = flag;
		int[] M = new int[64];
		int[] MIP_1 = new int[64];
		// �ر�ע�⣺xxx[IP[i]-1]�����Ʊ任
		for (i = 0; i < 64; i++) {
			M[i] = timeData[IP[i] - 1]; // ����IP�任
		}
		if (flags == 1) { // ����
			for (i = 0; i < 16; i++) {
				LoopF(M, i, flags, keyarray);
			}
		} else if (flags == 0) { // ����
			for (i = 15; i > -1; i--) {
				LoopF(M, i, flags, keyarray);
			}
		}
		for (i = 0; i < 64; i++) {
			MIP_1[i] = M[IP_1[i] - 1]; // ����IP-1����
		}
		GetEncryptResultOfByteArray(MIP_1, encrypt);
		// ���ؼ������
		return encrypt;
	}

	private int[] ReadDataToBirnaryIntArray(byte[] intdata) {
		int i;
		int j;
		// �����ת��Ϊ��������洢������
		int[] IntDa = new int[8];
		for (i = 0; i < 8; i++) {
			IntDa[i] = intdata[i];
			if (IntDa[i] < 0) {
				IntDa[i] += 256;
				IntDa[i] %= 256;
			}
		}
		int[] IntVa = new int[64];
		for (i = 0; i < 8; i++) {
			for (j = 0; j < 8; j++) {
				IntVa[((i * 8) + 7) - j] = IntDa[i] % 2;
				IntDa[i] = IntDa[i] / 2;
			}
		}
		return IntVa;
	}

	private void LeftBitMove(int[] k, int offset) {
		int i;
		// ѭ����λ��������
		int[] c0 = new int[28];
		int[] d0 = new int[28];
		int[] c1 = new int[28];
		int[] d1 = new int[28];
		for (i = 0; i < 28; i++) {
			c0[i] = k[i];
			d0[i] = k[i + 28];
		}
		if (offset == 1) {
			for (i = 0; i < 27; i++) { // ѭ������һλ
				c1[i] = c0[i + 1];
				d1[i] = d0[i + 1];
			}
			c1[27] = c0[0];
			d1[27] = d0[0];
		} else if (offset == 2) {
			for (i = 0; i < 26; i++) { // ѭ��������λ
				c1[i] = c0[i + 2];
				d1[i] = d0[i + 2];
			}
			c1[26] = c0[0];
			d1[26] = d0[0];
			c1[27] = c0[1];
			d1[27] = d0[1];
		}
		for (i = 0; i < 28; i++) {
			k[i] = c1[i];
			k[i + 28] = d1[i];
		}
	}

	private void LoopF(int[] M, int times, int flag, int[][] keyarray) {
		int i;
		int j;
		int[] L0 = new int[32];
		int[] R0 = new int[32];
		int[] L1 = new int[32];
		int[] R1 = new int[32];
		int[] RE = new int[48];
		int[][] S = new int[8][6];
		int[] sBoxData = new int[8];
		int[] sValue = new int[32];
		int[] RP = new int[32];
		for (i = 0; i < 32; i++) {
			L0[i] = M[i]; // �������ĳ�ʼ��
			R0[i] = M[i + 32]; // �����Ҳ�ĳ�ʼ��
		}
		for (i = 0; i < 48; i++) {
			RE[i] = R0[E[i] - 1]; // ����E�任���䣬��32λ��Ϊ48λ
			RE[i] = RE[i] + keyarray[times][i]; // ��KeyArray[times][i]��λ������λ�ӷ�����
			if (RE[i] == 2) {
				RE[i] = 0;
			}
		}
		for (i = 0; i < 8; i++) { // 48λ�ֳ�8��
			for (j = 0; j < 6; j++) {
				S[i][j] = RE[(i * 6) + j];
			}
			// ���澭��S�У��õ�8����
			sBoxData[i] = S_Box[i][(S[i][0] << 1) + S[i][5]][(S[i][1] << 3)
					+ (S[i][2] << 2) + (S[i][3] << 1) + S[i][4]];
			// 8����任���������
			for (j = 0; j < 4; j++) {
				sValue[((i * 4) + 3) - j] = sBoxData[i] % 2;
				sBoxData[i] = sBoxData[i] / 2;
			}
		}
		for (i = 0; i < 32; i++) {
			RP[i] = sValue[P[i] - 1]; // ����P�任
			L1[i] = R0[i]; // �ұ��Ƶ����
			R1[i] = L0[i] + RP[i];
			if (R1[i] == 2) {
				R1[i] = 0;
			}
			// ���ºϳ�M����������M
			// ���һ�α任ʱ�����Ҳ����л������˴��������α任ʵ�ֲ���
			if (((flag == 0) && (times == 0)) || ((flag == 1) && (times == 15))) {
				M[i] = R1[i];
				M[i + 32] = L1[i];
			} else {
				M[i] = L1[i];
				M[i + 32] = R1[i];
			}
		}
	}

	private void GetEncryptResultOfByteArray(int[] data, byte[] value) {
		int i;
		int j;
		// ���洢64λ��������ݵ������е����ת��Ϊ�˸�����byte��
		for (i = 0; i < 8; i++) {
			for (j = 0; j < 8; j++) {
				value[i] += (data[(i << 3) + j] << (7 - j));
			}
		}
		for (i = 0; i < 8; i++) {
			value[i] %= 256;
			if (value[i] > 128) {
				value[i] -= 255;
			}
		}
	}

	public void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos,
			int length) {
		if (dest != null && src != null) {// ����������Ϊ��ʱ
			byte[] temp = new byte[length];
			for (int i = 0; i < length; i++) {
				temp[i] = src[srcPos + i];
			}
			for (int i = 0; i < length; i++) {
				dest[destPos + i] = temp[i];
			}
		}
	}

	private byte[] ByteDataFormat(byte[] data) {
		int len = data.length;
		int padlen = 8 - (len % 8);
		int newlen = len + padlen;
		byte[] newdata = new byte[newlen];
		arraycopy(data, 0, newdata, 0, len);
		for (int i = len; i < newlen; i++)
			newdata[i] = (byte) padlen;
		return newdata;
	}

	
	public byte[] DesEncrypt(byte[] des_key, byte[] des_data, int flag) {// SingleDes
		byte[] TpBuf = new byte[16];
		byte[] format_key = ByteDataFormat(des_key);
		byte[] format_data = ByteDataFormat(des_data);
		int datalen = format_data.length;
		int unitcount = datalen / 16;
		byte[] result_data = new byte[datalen / 2];// �޸�
		for (int i = 0; i < unitcount; i++) {
			byte[] tmpkey = new byte[8];
			byte[] tmpdata = new byte[8];
			arraycopy(format_key, 0, tmpkey, 0, 8);
			arraycopy(format_data, i * 8, tmpdata, 0, 8);
			byte[] tmpresult = UnitDes(tmpkey, tmpdata, flag);
			arraycopy(tmpresult, 0, result_data, i * 8, 8);
		}
		if (unitcount == 4) {
			arraycopy(result_data, 0, TpBuf, 0, 16);
			return TpBuf;
		} else
			return result_data;
	}
	
	public byte[] TripleDes(byte[] des_key, byte[] des_data, int flag){
		
		byte[] result=new byte[des_data.length];
		int times = des_data.length/8;
		byte[] oneTimeDesData;
		byte[] oneTimeDesResult;
		for(int i=0;i<times;i++){
			oneTimeDesData = Arrays.copyOfRange(des_data, i*8, i*8+8);
			oneTimeDesResult = TripleDesEncrypt(des_key,oneTimeDesData,flag);
			System.arraycopy(oneTimeDesResult, 0, result, i*8, 8);
		}
		
		return result;
	}
	
	public byte[] TripleDesEncrypt(byte[] des_key, byte[] des_data, int flag) {// TripleDes
		byte[] result = null;
		byte[] Tmp1 = null;
		byte[] Tmp2 = null;
		byte[] key1 = new byte[8];
		byte[] key2 = new byte[8];
		byte[] key3 = new byte[8];
		System.arraycopy(des_key, 0, key1, 0, 8);
		System.arraycopy(des_key, 8, key2, 0, 8);
		System.arraycopy(des_key, 0, key3, 0, 8);

		if (flag == 1)// ����
		{
			Tmp1 = DesEncrypt(key1, des_data, 1);
			Tmp2 = DesEncrypt(key2, Tmp1, 0);
			result = DesEncrypt(key3, Tmp2, 1);
		} else// ����
		{
			Tmp1 = DesEncrypt(key3, des_data, 0);
			Tmp2 = DesEncrypt(key2, Tmp1, 1);
			result = DesEncrypt(key1, Tmp2, 0);

		}

		return result;
	}
		
		public byte[] Mac(byte[] des_key,byte[] des_data,byte[] intv){
			
			
			String fillHex="";
			
			if (des_data.length%8==0){
				des_data = HexStringUtil.hexStringToBytes(HexStringUtil.bytesToHexString(des_data)+"8000000000000000");
			}else{
				des_data = HexStringUtil.hexStringToBytes(HexStringUtil.bytesToHexString(des_data)+"80");
				if (des_data.length%8!=0){
					for(int i=0;i<8-des_data.length%8;i++){
						fillHex += "00";
					}
					des_data = HexStringUtil.hexStringToBytes(HexStringUtil.bytesToHexString(des_data)+fillHex);
				}
			}
			
			int blockNum = des_data.length/8;
			byte[] tmpKey = new byte[8];
			System.arraycopy(des_key, 0, tmpKey, 0, 8);
			byte[] blockData=new byte[8];
			byte[] xorKey;
			xorKey = intv;
			for(int i=0;i<blockNum;i++){
				System.arraycopy(des_data, i*8, blockData, 0, 8);
				XOR(blockData,xorKey,8);
				if (i==blockNum-1){//3des
					xorKey = TripleDesEncrypt(des_key,blockData,1);
				}else{//des

					xorKey = DesEncrypt(tmpKey,blockData,1);
				}
				
			}
			//System.out.println(HexStringUtil.bytesToHexString(xorKey));
			byte[] mac = new byte[4];
			System.arraycopy(xorKey, 0, mac, 0, 4);
			return mac;
		}
	

		/*public byte[] Mac(byte[] des_key, byte[] des_data, byte[] intv,
			int des_data_len) {
		byte[] Mac = new byte[4];
		byte[] TmpBuf = new byte[8];
		byte[] Dn = new byte[] { (byte) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00 };
		byte[] Dx = new byte[8];
		byte[] tmpKey = new byte[8];
		int i, dLen = des_data_len;
		// int len = 8;
		System.arraycopy(Invt, 0, Dx, 0, 0x08);

		
		if (des_key.length == 0x08) {
			for (i = 0; i < dLen / 8; i++) {
				System.arraycopy(des_data, i * 8, TmpBuf, 0, 8);
				XOR(Dx, TmpBuf, 8);
				Dx = DesEncrypt(des_key, Dx, 1);

			}
			dLen = des_data_len % 0x08;
			System.arraycopy(des_data, des_data_len - dLen, TmpBuf, 0, dLen);
			System.arraycopy(Dn, 0, TmpBuf, dLen, 8 - dLen);
			XOR(Dx, TmpBuf, 8);
			TmpBuf = DesEncrypt(des_key, Dx, 1);
			System.arraycopy(TmpBuf, 0, Mac, 0, 4);
		}
		
		else {
			for (i = 0; i < dLen / 8; i++) {
				System.arraycopy(des_data, i * 8, TmpBuf, 0, 8);
				XOR(Dx, TmpBuf, 0x08);
				Dx = DesEncrypt(des_key, Dx, 1);
			}
			dLen = des_data_len % 0x08;
			System.arraycopy(des_data, des_data_len - dLen, TmpBuf, 0, dLen);
			System.arraycopy(Dn, 0, TmpBuf, dLen, 8 - dLen);
			XOR(Dx, TmpBuf, 8);
			TmpBuf = DesEncrypt(des_key, Dx, 1);
			System.arraycopy(des_key, 8, tmpKey, 0, 8);
			TmpBuf = DesEncrypt(tmpKey, TmpBuf, 0);
			TmpBuf = DesEncrypt(des_key, TmpBuf, 1);
			System.arraycopy(TmpBuf, 0, Mac, 0, 4);
		}
		return Mac;

	}*/

	public void XOR(byte[] buf, byte[] key, int len) {
		while (len > 0) {
			buf[len - 1] ^= key[len - 1];
			len--;
		}
	}

	
	
	public byte[] buildUTKSessionKey(byte[] sequence1,byte[] random1){
		
		byte[] sequence = new byte[sequence1.length];
		byte[] random = new byte[random1.length];
		
		System.arraycopy(sequence1, 0, sequence, 0, sequence1.length);
		System.arraycopy(random1, 0, random, 0, random1.length);
		
		byte[] rootKey = HexStringUtil.hexStringToBytes(ConfigProperties.getInstance().getValue("utk.rootKey"));
		byte[] sessionKey = new byte[16];
		byte[] onceHashKey = new byte[16];
		
		System.arraycopy(TripleDes(rootKey, sequence, 1), 0, onceHashKey, 0, 8);
		XOR(sequence, HexStringUtil.hexStringToBytes("FFFFFFFFFFFFFFFF"), 8);
		System.arraycopy(TripleDes(rootKey, sequence, 1), 0, onceHashKey, 8, 8);
		
		byte[] randomFilled=HexStringUtil.hexStringToBytes(HexStringUtil.bytesToHexString(random)+"20202020");
		System.arraycopy(TripleDes(onceHashKey, randomFilled, 1), 0, sessionKey, 0, 8);
		//对randomFilled求反,即异或8字节0xFF
		XOR(randomFilled, HexStringUtil.hexStringToBytes("FFFFFFFFFFFFFFFF"), 8);
		System.arraycopy(TripleDes(onceHashKey, randomFilled, 1), 0, sessionKey, 8, 8);
		
		return sessionKey;
	}
	
	public byte[] buildMac1Key(byte[] sequence1,byte[] random1){
		
		byte[] sequence = new byte[16];
		byte[] random = new byte[16];
		
		//System.arraycopy(sequence1, 0, sequence, 0, sequence1.length);
		//System.arraycopy(random1, 0, random, 0, random1.length);
		
		byte[] rootKey = HexStringUtil.hexStringToBytes(ConfigProperties.getInstance().getValue("utk.rootKey"));
		byte[] sessionKey = new byte[16];
		byte[] onceHashKey = new byte[16];
		
		System.arraycopy(TripleDes(rootKey, sequence, 1), 0, onceHashKey, 0, 8);
		XOR(sequence, HexStringUtil.hexStringToBytes("FFFFFFFFFFFFFFFF"), 8);
		System.arraycopy(TripleDes(rootKey, sequence, 1), 0, onceHashKey, 8, 8);
		
		
		onceHashKey = HexStringUtil.hexStringToBytes("10112233445566778899AABBCCDDEEFF ");
		
		byte[] randomFilled=HexStringUtil.hexStringToBytes("5F63E28A00008000");
		System.arraycopy(TripleDes(onceHashKey, randomFilled, 1), 0, sessionKey, 0, 8);
		//对randomFilled求反,即异或8字节0xFF
		XOR(randomFilled, HexStringUtil.hexStringToBytes("FFFFFFFFFFFFFFFF"), 8);
		System.arraycopy(TripleDes(onceHashKey, randomFilled, 1), 0, sessionKey, 8, 8);
		
		System.out.println(HexStringUtil.bytesToHexString(sessionKey));
		return sessionKey;
	}
	
	
	public static void main(String args[]) {
		PBOCUtil test = new PBOCUtil();
		/*test.Keynm=hexStringToBytes("96D9346A42402D1741564B7F220D6929");
		test.SdNumber=hexStringToBytes("0000000000000000");
		System.out.println(HexStringUtil.bytesToHexString(test.TripleDes(test.Keynm, test.SdNumber,1)));
		
		//byte[] keyByte = HexStringUtil.hexStringToBytes("3130fbf5dec13687feaa063452adcbc6".toUpperCase());
		//byte[] text = HexStringUtil.hexStringToBytes("2011050513481980002559322e3241313030353230100000000000000000000000000000000000000000000000000000000000000000003239393130323535392d32303131303432363139343531332e70617232303131303331343030303031372e6661723239393030333935372d32303131303432393134323431302e6175743239393130323535392d32303131303432363139343531332e75737200000000000000000000000000000000000000000000000000000000000000000000000020110505134819042011050513275402000000ffffffffffffffffffffff35".toUpperCase());
		
		byte[] keyByte = HexStringUtil.hexStringToBytes("4D5A33305A39435045524F3854425948".toUpperCase());
		byte[] text = HexStringUtil.hexStringToBytes("51800000811D2C0400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020110505164212202105051642120000000000000000800011221C".toUpperCase());
		
		byte[] intv = HexStringUtil.hexStringToBytes("0000000000000000");
		byte[] macResult = test.Mac(keyByte, text, intv);
		System.out.println(HexStringUtil.bytesToHexString(macResult));
		
		
		//test.Mac2(keyByte, text, intv);
		
		byte[] data1={0x11,0x22};
		byte[] data2={0x33,0x44};
		test.XOR(data1, data2, 2);
		System.out.println(HexStringUtil.bytesToHexString(data1));
		System.out.println(HexStringUtil.bytesToHexString(data2));
		
		
		System.out.print("gogoog="+HexStringUtil.asc2Hex("8AE69489"));*/
		
		
		//byte[] res1 = test.TripleDes(HexStringUtil.hexStringToBytes("01112233445566778899AABBCCDDEEFF"), HexStringUtil.hexStringToBytes("56D83A9C20202020"), 1);
		//System.out.println(HexStringUtil.bytesToHexString(res1));
		/*byte[] sequence = HexStringUtil.hexStringToBytes("0011075725448956");
		byte[] utkSessionKey=test.buildUTKSessionKey(sequence, HexStringUtil.hexStringToBytes("6D396937"));
		byte[] data=HexStringUtil.hexStringToBytes("EA07E455948FA3AFCA8C9592B3822B09F0F5EE23FDDFBF8C2D99A81A40144E25CD8B14FBF4B22BFDDDB99E2CD3109729ECB48A85AF914C9D641AAB3FC3654183");
		byte[] mingwen=test.TripleDes(utkSessionKey, data, 0);
		
		System.out.println("key=\n"+HexStringUtil.bytesToHexString(utkSessionKey));
		System.out.println("mingwen=\n"+HexStringUtil.bytesToHexString(mingwen));
		*/
		
		//test.buildMac1Key(null, null);
		byte[] cardSequence = HexStringUtil.hexStringToBytes("0011075725448956");
		byte[] random=HexStringUtil.hexStringToBytes("AABBCCDD");
		byte[] sessionKey=test.buildUTKSessionKey(cardSequence, random);
		byte[] data = HexStringUtil.hexStringToBytes("0102030405060708010203040506070801020304050607080102030405060708");
		byte[] miwen=test.TripleDes(sessionKey, data, 1);
		System.out.println("miwen="+HexStringUtil.bytesToHexString(miwen));
		
	}
}
